package com.runvp.common.util.enc;

import javax.crypto.Cipher;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Base64;

public class AesGcmDecryptExample {
    public static void main(String[] args) throws Exception {
        // 给定的密钥、IV、Tag和密文（已转换为字节）
        String keyBase64 = "BMrcujdO0XDjvOOa";
        String ivBase64 = "98BPRR4Wve41";
        String tagHex = "7130C4C92F60B7EB4D565B1DDFC2559E";
        String ciphertextHex = "6BE3153AFC79025ACDF03CB38D988927BBF1DB4FCE387729CB19AB13FEC136";

        // 将Base64编码的密钥和IV转换为字节数组
        byte[] keyBytes = Base64.getDecoder().decode(keyBase64);
        byte[] ivBytes = Base64.getDecoder().decode(ivBase64);

        // 将十六进制的Tag和密文转换为字节数组
        byte[] tagBytes = hexStringToByteArray(tagHex);
        byte[] ciphertextBytes = hexStringToByteArray(ciphertextHex);

        // 创建AES密钥规范
        SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");

        // 创建GCM参数规范，注意Tag长度默认为128位（16字节）
        AlgorithmParameterSpec gcmParamSpec = new GCMParameterSpec(128, ivBytes);

        // 初始化Cipher对象为解密模式
        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
        cipher.init(Cipher.DECRYPT_MODE, keySpec, gcmParamSpec);

        // 添加认证标签到Cipher对象
        cipher.updateAAD(tagBytes);

        // 解密密文并去除Tag（如果Tag包含在密文中，则需调整处理逻辑）
        byte[] decryptedBytes = cipher.doFinal(ciphertextBytes);

        // 转换解密后的字节为字符串输出
        String decryptedText = new String(decryptedBytes, StandardCharsets.UTF_8);
        System.out.println("Decrypted Text: " + decryptedText);
    }

    // 辅助方法：将十六进制字符串转换为字节数组
    private static byte[] hexStringToByteArray(String s) {
        int len = s.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                    + Character.digit(s.charAt(i+1), 16));
        }
        return data;
    }
}